Master Pythoni unittest.mock teegi. SĂĽgav sukeldumine test double'itesse, mock objektidesse, stub'idesse, fake'idesse ja patch dekoratsioonisse vastupidavaks, isoleeritud ĂĽhiktestimiseks.
Python Mock Objekti: Põhjalik juhend Test Double'i rakendamiseks
Kaasaegse tarkvaraarenduse maailmas on koodi kirjutamine vaid pool lahingust. See, et kood on usaldusväärne, vastupidav ja töötab ootuspäraselt, on teine, sama kriitiline pool. Siin tulebki mängu automatiseeritud testimine. Eriti ühiktestimine on aluspõhimõte, mis hõlmab rakenduse üksikute komponentide ehk „ühikute“ isoleeritud testimist. Selle isolatsiooni saavutamine on aga sageli lihtsam öelda kui teha. Tõelised rakendused on keerulised omavahel ühendatud objektide, teenuste ja väliste süsteemide võrgustikud. Kuidas saate testida ühte funktsiooni, kui see sõltub andmebaasist, kolmanda osapoole API-st või teie süsteemi muust keerulisest osast?
Vastus peitub võimsas tehnikas: Test Double'ide kasutamises. Ja Pythoni ökosüsteemis on nende loomiseks peamine tööriist mitmekülgne ja asendamatu unittest.mock teek. See juhend viib teid sügavale Pythoni mock'ide ja test double'ide maailma. Uurime nende tagamaid, demüstifitseerime erinevaid tüüpe ja pakume praktilisi, reaalseid näiteid unittest.mock abil, et aidata teil kirjutada puhtamaid, kiiremaid ja tõhusamaid teste.
Mis on Test Double'id ja miks me neid vajame?
Kujutage ette, et ehitate funktsiooni, mis hankib teie ettevõtte andmebaasist kasutaja profiili ja vormindab selle. Funktsiooni allkiri võiks välja näha selline: get_formatted_user_profile(user_id, db_connection).
Selle funktsiooni testimiseks seisate silmitsi mitmete väljakutsetega:
- Sõltuvus otseühendusega süsteemist: Teie test vajaks töötavat andmebaasi. See muudab testid aeglaseks, keeruliseks seadistada ja sõltuvaks välissüsteemi olekust ja kättesaadavusest.
- Ettearvamatus: Andmebaasi andmed võivad muutuda, põhjustades teie testi ebaõnnestumise isegi siis, kui teie vormindusloogika on õige. See muudab testid „krüptilisteks“ ehk deterministlikuks.
- Äärmuslike juhtumite testimise raskus: Kuidas testida, mis juhtub, kui andmebaasiühendus ebaõnnestub või kui see tagastab kasutaja, kellel puudub osa andmeid? Nende konkreetsete stsenaariumide simuleerimine tõelise andmebaasiga võib olla äärmiselt keeruline.
Test Double on üldine termin mis tahes objekti kohta, mis asendab reaalset objekti testi ajal. Asendades reaalse db_connection test double'iga, saame katkestada sõltuvuse tegelikust andmebaasist ja võtta testimiskeskkonna täielikult kontrolli alla.
Test double'ide kasutamine pakub mitmeid peamisi eeliseid:
- Isolatsioon: Need võimaldavad teil testida oma koodiühikut (nt vormindusloogikat) täielikult isoleeritult selle sõltuvustest (nt andmebaasist). Kui test ebaõnnestub, teate, et probleem on testitavas ühikus, mitte mujal.
- Kiirus: Aeglaste toimingute, nagu võrgupäringute või andmebaasipäringute asendamine mälus olevate test double'idega, muudab teie testide komplekti oluliselt kiiremaks. Kiired testid käivitatakse sagedamini, mis viib tihedama tagasisideahela arendajateni.
- Deterministlikkus: Saate test double'i konfigureerida nii, et see tagastab iga kord testide käivitamisel ettearvatavaid andmeid. See kõrvaldab krüptilised testid ja tagab, et ebaõnnestunud test näitab tõelist probleemi.
- Äärmuslike juhtumite testimise võime: Saate hõlpsasti konfigureerida double'i, et simuleerida veatingimusi, nagu
ConnectionErrortõstmine või tühjade andmete tagastamine, mis võimaldab teil kontrollida, kas teie kood käsitleb neid olukordi graatsiliselt.
Test Double'ide taksonoomia: rohkem kui lihtsalt "Mock'id"
Kuigi arendajad kasutavad sageli terminit „mock“ üldiselt mis tahes test double'i tähistamiseks, on kasulik mõista Gerard Meszarose oma raamatus „xUnit Test Patterns“ loodud täpsemaid termineid. Nende erinevuste tundmine aitab teil selgemalt mõelda selle üle, mida te oma testis saavutada üritate.
1. Dummy
Dummy objekt on kõige lihtsam test double. Seda edastatakse, et täita parameetrite loendit, kuid seda ei kasutata kunagi tegelikult. Selle meetodeid tavaliselt ei kutsuta. Kasutate dummy-objekti, kui peate meetodi jaoks argumendi pakkuma, kuid te ei hooli selle argumendi käitumisest konkreetse testi kontekstis.
Näide: Kui funktsioon nõuab „logger“-objekti, kuid teie test ei puuduta seda, mida logitakse, võite edastada dummy-objekti.
2. Fake
Fake-objektil on töötav implementatsioon, kuid see on tootmisobjekti palju lihtsam versioon. See ei kasuta väliseid ressursse ja asendab raskekaalulise rakenduse kerge kaaluga rakendusega. Klassikaline näide on mälus olev andmebaas, mis asendab tegeliku andmebaasiühenduse. See töötab tegelikult – saate sellesse andmeid lisada ja seda lugeda – kuid selle all on lihtsalt lihtne sõnastik või loend.
3. Stub
Stub pakub eelprogrammeeritud, „pakendatud“ vastuseid testide ajal tehtud meetodikutsumistele. Seda kasutatakse siis, kui teie kood peab saama sõltuvuselt konkreetseid andmeid. Näiteks võiksite stub'ida meetodi api_client.get_user(user_id=123) nii, et see tagastaks alati konkreetse kasutaja sõnastiku, ilma tegelikku API-päringut tegemata.
4. Spy
Spy on stub, mis salvestab ka infot selle kohta, kuidas seda kutsuti. Näiteks võib see salvestada meetodi kutsumiste arvu või sellele edastatud argumendid. See võimaldab teil oma koodi ja selle sõltuvuse vahelist suhtlust „spioneerida“ ja seejärel hiljem nende interaktsioonide kohta väiteid esitada.
5. Mock
Mock on kõige „teadlikum“ test double tüüp. See on objekt, mis on eelprogrammeeritud ootustega selle kohta, milliseid meetodeid kutsutakse, milliste argumentidega ja millises järjekorras. Mock-objektiga test ebaõnnestub mitte ainult siis, kui testitav kood annab vale tulemuse, vaid ka siis, kui see ei suhtle mock'iga täpselt oodatud viisil. Mock'id sobivad suurepäraselt käitumise kontrollimiseks – tagades, et toimus konkreetne tegevuste järjestus.
Pythoni unittest.mock teek pakub ühte võimsat klassi, mis võib toimida Stub'ina, Spy'na või Mock'ina, sõltuvalt sellest, kuidas te seda kasutate.
Tutvustus Pythoni Võimsuses: `unittest.mock` Teek
Alates Pythoni standardteegi versioonist 3.3 on unittest.mock kanooniline lahendus test double'ide loomiseks. Selle paindlikkus ja võimsus muudavad selle iga tõsise Pythoni arendaja jaoks hädavajalikuks tööriistaks. Kui kasutate vanemat Pythoni versiooni, saate tagasiühilduva teegi installida pip kaudu: pip install mock.
Teegi keskmes on kaks peamist klassi: Mock ja selle võimekam vend MagicMock. Need objektid on loodud olema äärmiselt paindlikud, luues atribuute ja meetodeid lendu nende juurde pääsemisel.
SĂĽgav Sukeldumine: `Mock` ja `MagicMock` Klassid
`Mock` Objekt
Mock objekt on kameeleon. Saate selle luua ja see reageerib kohe igale atribuudi juurdepääsule või meetodikutsumisele, tagastades vaikimisi teise Mock objekti. See võimaldab teil seadistamise ajal meetodikutsumisi hõlpsasti aheldada.
# Testifailis...
from unittest.mock import Mock
# Looge mock objekt
mock_api = Mock()
# Atribuudi juurdepääs loob selle ja tagastab teise moki
print(mock_api.users)
# Väljund: <Mock name='mock.users' id='...'>
# Meetodi kutsumine tagastab ka vaikimisi moki
print(mock_api.users.get(id=1))
# Väljund: <Mock name='mock.users.get()' id='...'>
See vaikimisi käitumine pole testimiseks eriti kasulik. Tõeline võimsus seisneb moki konfigureerimises nii, et see käituks nagu objekti, mida see asendab.
Tagastusväärtuste ja kõrvalmõjude konfigureerimine
Saate moki meetodile öelda, mida tagastada, kasutades return_value atribuuti. Nii loote Stub'i.
from unittest.mock import Mock
# Looge andmeteenuse jaoks mock
mock_service = Mock()
# Konfigureerige meetodi tagastusväärtus
mock_service.get_data.return_value = {'id': 1, 'name': 'Test Data'}
# Nüüd, kui kutsume seda, saame meie konfigureeritud väärtuse
result = mock_service.get_data()
print(result)
# Väljund: {'id': 1, 'name': 'Test Data'}
Vigade simuleerimiseks saate kasutada side_effect atribuuti. See sobib suurepäraselt teie koodi veakäsitluse testimiseks.
from unittest.mock import Mock
mock_service = Mock()
# Konfigureerige meetod tõstma erandi
mock_service.get_data.side_effect = ConnectionError("Failed to connect to service")
# Meetodi kutsumine tõstab nüüd erandi
try:
mock_service.get_data()
except ConnectionError as e:
print(e)
# Väljund: Failed to connect to service
Kontrollimiseks mõeldud väite meetodid
Mock objektid toimivad ka kui Spy'd ja Mock'id, salvestades, kuidas neid kasutati. Seejärel saate nende interaktsioonide kontrollimiseks kasutada sisseehitatud väite meetodite komplekti.
mock_object.method.assert_called(): Väidab, et meetodit kutsuti vähemalt üks kord.mock_object.method.assert_called_once(): Väidab, et meetodit kutsuti täpselt üks kord.mock_object.method.assert_called_with(*args, **kwargs): Väidab, et meetodit kutsuti viimati määratud argumentidega.mock_object.method.assert_any_call(*args, **kwargs): Väidab, et meetodit kutsuti nende argumentidega igal ajal.mock_object.method.assert_not_called(): Väidab, et meetodit ei kutsutud kunagi.mock_object.call_count: Täisarvuline atribuut, mis näitab, mitu korda meetodit kutsuti.
from unittest.mock import Mock
mock_notifier = Mock()
# Kujutage ette, et see on meie testitav funktsioon
def process_and_notify(data, notifier):
if data.get('critical'):
notifier.send_alert(message="Critical event occurred!")
# Testjuhtum 1: Kriitilised andmed
process_and_notify({'critical': True}, mock_notifier)
mock_notifier.send_alert.assert_called_once_with(message="Critical event occurred!")
# Nullige mock järgmiseks testiks
mock_notifier.reset_mock()
# Testjuhtum 2: Mittekriitilised andmed
process_and_notify({'critical': False}, mock_notifier)
mock_notifier.send_alert.assert_not_called()
`MagicMock` Objekt
MagicMock on Mock'i alamklass peamise erinevusega: sellel on enamiku Pythoni „maagiliste“ ehk „dunder“ meetodite (nt __len__, __str__, __iter__) vaikimisi implementatsioonid. Kui proovite kasutada tavalist Mock'i kontekstis, mis nõuab ühte neist meetoditest, saate vea.
from unittest.mock import Mock, MagicMock
# Tavaline Mocki kasutamine
mock_list = Mock()
try:
len(mock_list)
except TypeError as e:
print(e) # Väljund: 'Mock' object has no len()
# MagicMocki kasutamine
magic_mock_list = MagicMock()
print(len(magic_mock_list)) # Väljund: 0 (vaikimisi)
# Saame ka maagilise meetodi tagastusväärtust konfigureerida
magic_mock_list.__len__.return_value = 100
print(len(magic_mock_list)) # Väljund: 100
Üldreegel: Alustage MagicMock'iga. See on üldiselt turvalisem ja katab rohkem kasutusjuhtumeid, nagu objektide mockimine, mida kasutatakse for-tsüklites (nõudes __iter__) või with-lausetes (nõudes __enter__ ja __exit__).
Praktiline Rakendamine: `patch` Dekoratsioon ja Kontekstihaldur
Mock'i loomine on üks asi, kuid kuidas panna oma kood seda kasutama reaalse objekti asemel? Siin tuleb mängu `patch`. `patch` on unittest.mock'i võimas tööriist, mis asendab sihtmärgina objekti ajutiselt mock'iga testi kestel.
`@patch` Dekoratsioonina
Kõige tavalisem viis `patch` kasutamiseks on dekoratsioonina teie testimeetodil. Te annate stringi tee objektini, mida soovite asendada.
Oletame, et meil on funktsioon, mis hangib andmeid veebiakust kasutades populaarset `requests` teeki:
# failis: my_app/data_fetcher.py
import requests
def get_user_data(user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
response.raise_for_status() # Tõstab erandi vigaste olekukoodide korral
return response.json()
Soovime seda funktsiooni testida ilma tegelikku võrgupäringut tegemata. Saame `requests.get`'i parandada:
# failis: tests/test_data_fetcher.py
import unittest
from unittest.mock import patch, Mock
from my_app.data_fetcher import get_user_data
class TestDataFetcher(unittest.TestCase):
@patch('my_app.data_fetcher.requests.get')
def test_get_user_data_success(self, mock_get):
"""Test edukas andmete hankimine."""
# Konfigureerige mock edukalt API vastuse simuleerimiseks
mock_response = Mock()
mock_response.json.return_value = {'id': 1, 'name': 'John Doe'}
mock_response.raise_for_status.return_value = None # Edu korral midagi ei tee
mock_get.return_value = mock_response
# Kutsuge meie funktsiooni
user_data = get_user_data(1)
# Kinnitage, et meie funktsioon tegi õige API-päringu
mock_get.assert_called_once_with('https://api.example.com/users/1')
# Kinnitage, et meie funktsioon tagastas oodatud andmed
self.assertEqual(user_data, {'id': 1, 'name': 'John Doe'})
Pange tähele, kuidas `patch` loob MagicMock'i ja edastab selle meie testimeetodisse `mock_get` argumendina. Testi sees suunatakse kõik `requests.get` kutsumised `my_app.data_fetcher` sees meie mock objektile.
`patch` Kontekstihaldurina
Mõnikord vajate midagi parandada ainult testi väikese osa jaoks. `patch`'i kasutamine kontekstihaldurina koos `with` lausega on selleks ideaalne.
# failis: tests/test_data_fetcher.py
import unittest
from unittest.mock import patch, Mock
from my_app.data_fetcher import get_user_data
class TestDataFetcher(unittest.TestCase):
def test_get_user_data_with_context_manager(self):
"""Test patch'i kasutamist kontekstihaldurina."""
with patch('my_app.data_fetcher.requests.get') as mock_get:
# Konfigureerige mock 'with' ploki sees
mock_response = Mock()
mock_response.json.return_value = {'id': 2, 'name': 'Jane Doe'}
mock_get.return_value = mock_response
user_data = get_user_data(2)
mock_get.assert_called_once_with('https://api.example.com/users/2')
self.assertEqual(user_data, {'id': 2, 'name': 'Jane Doe'})
# 'with' plokist väljaspool on requests.get oma algsesse olekusse tagasi
Oluline Mõiste: Kus Parandada?
See on kõige tavalisem segaduse allikas `patch`'i kasutamisel. Reegel on: Peate parandama objekti seal, kus seda otsitakse, mitte seal, kus seda on defineeritud.
Illustreerime näitega. Oletame, et meil on kaks faili:
# failis: services.py
class Database:
def connect(self):
# ... keeruline ĂĽhendusloogika ...
return "REAL_CONNECTION"
# failis: main_app.py
from services import Database
def start_app():
db = Database()
connection = db.connect()
print(f"Got connection: {connection}")
return connection
NĂĽĂĽd tahame testida `start_app` funktsiooni `main_app.py` failis, ilma et tegelikku Database objekti luua. Levinud viga on proovida parandada `services.Database`.
# failis: test_main_app.py
import unittest
from unittest.mock import patch
from main_app import start_app
class TestApp(unittest.TestCase):
# SEE ON VALE VIIS PARANDADA!
@patch('services.Database')
def test_start_app_incorrectly(self, mock_db):
start_app()
# See test kasutab ikka VEEL reaalset Database klassi!
# SEE ON ÕIGE VIIS PARANDADA!
@patch('main_app.Database')
def test_start_app_correctly(self, mock_db_class):
# Me parandame 'Database' nime 'main_app' nimiruumis
# Konfigureerige loodav mock-eksemplar
mock_instance = mock_db_class.return_value
mock_instance.connect.return_value = "MOCKED_CONNECTION"
connection = start_app()
# Kinnitage, et meie mocki kasutati
mock_db_class.assert_called_once() # Kas klassi instantiati?
mock_instance.connect.assert_called_once() # Kas connect meetodit kutsuti?
self.assertEqual(connection, "MOCKED_CONNECTION")
Miks esimene test ebaõnnestub? Sest `main_app.py` täidab `from services import Database`. See impordib Database klassi `main_app` mooduli nimiruumi. Kui `start_app` käivitub, otsib see `Database`'i oma enda moodulist (`main_app`). `services.Database` parandamine muudab seda `services` moodulis, kuid `main_app`'il on juba oma viide algsele klassile. Õige lähenemine on parandada `main_app.Database`, mis on nimi, mida testitav kood tegelikult kasutab.
Täpsemad Mocking-Tehnikad
`spec` ja `autospec`: Mockide Turvalisemaks Muutmine
Tavaline MagicMock on potentsiaalse puudusega: see võimaldab teil kutsuda mis tahes meetodit mis tahes argumentidega, isegi kui see meetod ei eksisteeri reaalsel objektil. See võib viia testideni, mis läbivad, kuid varjavad reaalseid probleeme, nagu meetodinimede trükivead või reaalse objekti API muutused.
# Reaalne klass
class Notifier:
def send_message(self, text):
# ... saadab sõnumi ...
pass
# Test koos trĂĽkiveaga
from unittest.mock import MagicMock
mock_notifier = MagicMock()
# Oh, trĂĽkiviga! Tegelik meetod on send_message
mock_notifier.send_mesage("hello") # Viga ei tõsteta!
mock_notifier.send_mesage.assert_called_with("hello") # See väide läbib!
# Meie test on roheline, kuid tootmiskood ebaõnnestuks.
Selle vältimiseks pakub unittest.mock argumente `spec` ja `autospec`.
spec=SomeClass: See konfigureerib moki nii, et sellel oleks sama API nagu `SomeClass`'il. Kui proovite juurde pääseda meetodile või atribuudile, mis ei eksisteeri reaalajas klassis, tõstetakse `AttributeError`.autospec=True(võiautospec=SomeClass): See on veelgi võimsam. See toimib nagu `spec`, kuid kontrollib ka mis tahes mockitud meetodite kutse signatuuri. Kui kutsute meetodit vale arvu või nimedega argumentidega, tõstab see `TypeError`, nagu reaalne objekt seda teeks.
from unittest.mock import create_autospec
# Looge mock, millel on sama liides nagu meie Notifier klassil
spec_notifier = create_autospec(Notifier)
try:
# See ebaõnnestub koheselt trükivea tõttu
spec_notifier.send_mesage("hello")
except AttributeError as e:
print(e) # Väljund: Mock object has no attribute 'send_mesage'
try:
# See ebaõnnestub, sest signatuur on vale (puudub 'text' võti)
spec_notifier.send_message("hello")
except TypeError as e:
print(e) # Väljund: missing a required argument: 'text'
# Selle kutsumine on õige viis
spec_notifier.send_message(text="hello") # See töötab!
spec_notifier.send_message.assert_called_once_with(text="hello")
Parim tava: Kasutage alati `autospec=True` parandades. See muudab teie testid vastupidavamaks ja vähem hapraks. `@patch('path.to.thing', autospec=True)`.
Reaalmaailma Näide: Andmetöötluse Teenuse Testimine
Ühendame kõik kokku põhjalikuma näitega. Meil on ReportGenerator, mis sõltub andmebaasist ja failisüsteemist.
# failis: app/services.py
class DatabaseConnector:
def get_sales_data(self, start_date, end_date):
# Tegelikult teeks see päringu andmebaasi
raise NotImplementedError("This should not be called in tests")
class FileSaver:
def save_report(self, path, content):
# Tegelikult kirjutaks see faili
raise NotImplementedError("This should not be called in tests")
# failis: app/reports.py
from .services import DatabaseConnector, FileSaver
class ReportGenerator:
def __init__(self):
self.db_connector = DatabaseConnector()
self.file_saver = FileSaver()
def generate_sales_report(self, start_date, end_date, output_path):
"""Hankib mĂĽĂĽgiandmed ja salvestab vormindatud aruande."""
raw_data = self.db_connector.get_sales_data(start_date, end_date)
if not raw_data:
report_content = "No sales data for this period."
else:
total_sales = sum(item['amount'] for item in raw_data)
report_content = f"Total Sales from {start_date} to {end_date}: ${total_sales:.2f}"
self.file_saver.save_report(path=output_path, content=report_content)
return True
Nüüd kirjutame ühiktesti ReportGenerator.generate_sales_report funktsioonile, mis mockib selle sõltuvusi.
# failis: tests/test_reports.py
import unittest
from datetime import date
from unittest.mock import patch, Mock
from app.reports import ReportGenerator
class TestReportGenerator(unittest.TestCase):
@patch('app.reports.FileSaver', autospec=True)
@patch('app.reports.DatabaseConnector', autospec=True)
def test_generate_sales_report_with_data(self, mock_db_connector_class, mock_file_saver_class):
"""Test aruande genereerimist, kui andmebaas tagastab andmeid."""
# Korralda: seadistage meie mock'id
mock_db_instance = mock_db_connector_class.return_value
mock_file_saver_instance = mock_file_saver_class.return_value
# Konfigureerige andmebaasi mock tagastama mõned võltsandmed (Stub)
fake_data = [
{'id': 1, 'amount': 100.50},
{'id': 2, 'amount': 75.00},
{'id': 3, 'amount': 25.25}
]
mock_db_instance.get_sales_data.return_value = fake_data
start = date(2023, 1, 1)
end = date(2023, 1, 31)
path = '/reports/sales_jan_2023.txt'
# Toimi: looge meie klassi eksemplar ja kutsuge meetodit
generator = ReportGenerator()
result = generator.generate_sales_report(start, end, path)
# Kontrolli: kontrollige interaktsioone ja tulemusi
# 1. Kas andmebaasi kutsuti õigesti?
mock_db_instance.get_sales_data.assert_called_once_with(start, end)
# 2. Kas failisäästjat kutsuti õige, arvutatud sisuga?
expected_content = "Total Sales from 2023-01-01 to 2023-01-31: $200.75"
mock_file_saver_instance.save_report.assert_called_once_with(
path=path,
content=expected_content
)
# 3. Kas meie meetod tagastas õige väärtuse?
self.assertTrue(result)
See test isoleerib täiuslikult `generate_sales_report` sees oleva loogika andmebaasi ja failisüsteemi keerukusest, kontrollides samal ajal, et see nendega õigesti suhtleb.
Parimad tavad tõhusaks Mockinguks
- Hoidke Mock'id lihtsad: Test, mis nõuab väga keerulist mock-konfiguratsiooni, on sageli märk ( „testi lõhn“ ), et testitav ühik on liiga keeruline ja võib rikkuda Üksikvastutuse Printsiipi. Kaaluge tootmiskoodi refaktoreerimist.
- Mock'ige koostööpartnereid, mitte kõike: Te peaksite mockima ainult neid objekte, millega teie testitav ühik suhtleb (selle koostööpartnereid). Ärge mockige ise objekti, mida te testite.
- Eelistage
autospec=True: Nagu mainitud, muudab see teie testid vastupidavamaks, tagades, et moki liides vastab reaalajas objekti liidesele. See aitab püüda refaktoreerimisest tingitud probleeme. - Üks Mock testi kohta (ideaalis): Hea ühiktest keskendub ühele käitumisele või interaktsioonile. Kui leiate, et peate ühes testis mockima palju erinevaid objekte, võib olla parem jagada see mitmeks, rohkem keskendunud testiks.
- Ole oma väidetes täpne: Ärge lihtsalt kontrollige `mock.method.assert_called()`. Kasutage `assert_called_with(...)`, et tagada, et interaktsioon toimus õigete andmetega. See muudab teie testid väärtuslikumaks.
- Teie testid on dokumentatsioon: Kasutage oma testide ja mock-objektide jaoks selgeid ja kirjeldavaid nimesid (nt `mock_api_client`, `test_login_fails_on_network_error`). See muudab testi eesmärgi teistele arendajatele selgeks.
Kokkuvõte
Test double'id pole mitte ainult testimise tööriist; need on testitava, modulaarse ja hooldatava tarkvara projekteerimise aluspõhimõte. Asendades reaalsed sõltuvused kontrollitud asendustega, saate luua testide komplekti, mis on kiire, usaldusväärne ja suudab kontrollida teie rakenduse loogika iga nurka.
Pythoni unittest.mock teek pakub maailmatasemel tööriistakomplekti nende mustrite rakendamiseks. Omades MagicMock'i, patch'i ja autospec'i turvalisust, saate võime kirjutada tõeliselt isoleeritud ühikteste. See annab teile võimaluse ehitada keerulisi rakendusi enesekindlalt, teades, et teil on täpsete, sihipäraste testide turvavõrk, mis püüavad tagasikäike ja valideerivad uusi funktsioone. Nii et minge edasi, alustage parandamist ja ehitage täna vastupidavamaid Pythoni rakendusi.